/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package otcapp.experto;

import java.util.ArrayList;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import otcapp.dto.ExpedienteCedulaOtraDTO;
import otcapp.entidades.AsignacionProfesional;
import otcapp.entidades.Expediente;
import otcapp.entidades.Personal;
import otcapp.entidades.Pieza;
import otcapp.experto.excepciones.ExpertoAsignarProfesionalException;
import otcapp.fabricas.FabricaExpertos;
import persistencia.exceptions.ExcepcionFachada;
import persistencia.Fachada;

/**
 *
 * @author diego
 */
public class ExpertoAsignarProfesional extends Experto {

    public void asignarProfesionalPieza(Personal personal, ExpedienteCedulaOtraDTO piezaDTO, String observacion) throws ExpertoAsignarProfesionalException {
        
        if(piezaDTO.isFinalizada()){
            throw new ExpertoAsignarProfesionalException("La pieza está finalizada. No se puede asignar Profesional");
        }

        Pieza pieza = ((ExpertoConsultarPieza) FabricaExpertos.getInstancia().getExperto(FabricaExpertos.expertos.CONSULTAR_PIEZA)).buscarPiezaID(piezaDTO.getId());

        List<AsignacionProfesional> asignaciones = buscarAsignacionesActivas(pieza);

        verificarProfesional(personal, asignaciones);

        desactivarAsignaciones(personal, asignaciones);

        AsignacionProfesional nuevaAsignacion = new AsignacionProfesional();

        nuevaAsignacion.setActiva(true);
        nuevaAsignacion.setFechaAsignacion(Fachada.getInstancia().getFecha());
        nuevaAsignacion.setPieza((Expediente) pieza);
        nuevaAsignacion.setProfesionalAsignado(personal);
        nuevaAsignacion.setObservacion(observacion);
        try {
            Fachada.getInstancia().guardar(nuevaAsignacion);
        } catch (ExcepcionFachada ex) {
            throw new ExpertoAsignarProfesionalException("Error al realizar Asignación");
        }

    }

    /**
     * Verifica si el profesional ya se encuentra asignado a la pieza
     *
     * @param prof
     * @param asignaciones
     * @throws ExpertoAsignarProfesionalException
     */
    private void verificarProfesional(Personal prof, List<AsignacionProfesional> asignaciones) throws ExpertoAsignarProfesionalException {
        for (AsignacionProfesional asignacionProfesional : asignaciones) {
            if (asignacionProfesional.getProfesionalAsignado().equals(prof)) {
                throw new ExpertoAsignarProfesionalException(prof.getApellido() + ", " + prof.getNombre() + ": Ya está asignado a la pieza Ingresada.");
            }
        }
    }

    /**
     * Revisa las asignaciones, si ya hay una asignacion de un profesional del
     * mismo tipo, la desactiva. para luego poder realizar una reasignacion
     *
     * @param prof
     * @param asignaciones
     */
    private void desactivarAsignaciones(Personal prof, List<AsignacionProfesional> asignaciones) throws ExpertoAsignarProfesionalException {

        for (AsignacionProfesional asignacionProfesional : asignaciones) {
            if (asignacionProfesional.getProfesionalAsignado().getTipoPersonal().equals(prof.getTipoPersonal())) {
                asignacionProfesional.setActiva(false);
                try {
                    Fachada.getInstancia().guardar(asignacionProfesional);
                } catch (ExcepcionFachada ex) {
                    throw new ExpertoAsignarProfesionalException("Error al actualizar actualizaciones anteriores.");
                }
            }
        }

    }


    public void asignarProfesionalPieza(List<Personal> profesionales, ExpedienteCedulaOtraDTO pieza, String observacion) throws ExpertoAsignarProfesionalException {
        for (Personal profesional : profesionales) {
            asignarProfesionalPieza(profesional, pieza,observacion);
        }
    }

    /**
     * Busca todas las asignaciones activas de una pieza
     *
     * @param pieza
     * @return
     */
    public List buscarAsignacionesActivas(Pieza pieza) {
        Criteria criterioPieza = Fachada.getInstancia().crearCriterio(AsignacionProfesional.class);
        criterioPieza.add(Restrictions.eq("pieza", pieza));
        criterioPieza.add(Restrictions.eq("activa", true));
        return Fachada.getInstancia().buscar(AsignacionProfesional.class, criterioPieza);
    }
    
    public List buscarAsignacionesAnteriores(ExpedienteCedulaOtraDTO dtoPieza){
        List<AsignacionProfesional> asignacionesAnteriores = new ArrayList<>();
        Expediente pieza = (Expediente) ((ExpertoConsultarPieza)FabricaExpertos.getInstancia().getExperto(FabricaExpertos.expertos.CONSULTAR_PIEZA)).buscarPiezaID(dtoPieza.getId());
        for (AsignacionProfesional asignacionProfesional : pieza.getAsignacionProfesionales()) {
            if(!asignacionProfesional.isActiva()){
                asignacionesAnteriores.add(asignacionProfesional);
            }
        }
        return asignacionesAnteriores;
    }

    public List buscarPersonal() {
        String[] tipos = {"Psicólogo", "Trabajador Social"};
        Criteria criterio = Fachada.getInstancia().crearCriterio(Personal.class);
        criterio.createCriteria("tipoPersonal").add(Restrictions.in("nombreTipo", tipos));
        return Fachada.getInstancia().buscar(Personal.class, criterio);
    }

    public List buscarPsicologos() {
        Criteria criterio = Fachada.getInstancia().crearCriterio(Personal.class);
        criterio.createCriteria("tipoPersonal").add(Restrictions.eq("nombreTipo", "Psicólogo"));
        return Fachada.getInstancia().buscar(Personal.class, criterio);
    }

    public List buscarTrabajadorSocial() {
        Criteria criterio = Fachada.getInstancia().crearCriterio(Personal.class);
        criterio.createCriteria("tipoPersonal").add(Restrictions.eq("nombreTipo", "Trabajador Social"));
        return Fachada.getInstancia().buscar(Personal.class, criterio);
    }
}
